#include "stdafx.h"
#include "rsc_encoder.h"


// Construtor da Classe do Codificador Convolucional Recursivo Sistematico
rsc_encoder::rsc_encoder(unsigned int _N,unsigned int _K,unsigned int _M,unsigned int *** _G,unsigned int _ZEROTAIL_SIZE)
{

	unsigned int i,j,k;
	unsigned int temp1=0;

	N=_N; K=_K; M=_M; ZEROTAIL_SIZE=_ZEROTAIL_SIZE;

	initial_state=0; encoder_memory=0;

	shift_register_length=new unsigned int [K]; for(i=0;i<K;i++) shift_register_length[i]=0;

	G=new unsigned int ** [N]; for(i=0;i<N;i++) G[i]=new unsigned int * [K];
	for(i=0;i<N;i++)
	 for(j=0;j<K;j++) G[i][j]=new unsigned int [(M+1)];

	for(i=0;i<N;i++)
	 for(j=0;j<K;j++)
	  for(k=0;k<(M+1);k++) G[i][j][k]=_G[i][j][k];


	for(i=0;i<K;i++)
	 {
		temp1=0;
		j=M+1;
		do { j--; if (G[0][i][j]==1) shift_register_length[i]=j; } while((G[0][i][j]==0)&&(j>0));

		for(k=1;k<N;k++)
		  {
			  j=M+1;
			  do { j--; if (G[k][i][j]==1) temp1=j; } while((G[k][i][j]==0)&&(j>0));
			  if (temp1>shift_register_length[i]) shift_register_length[i]=temp1;
		  }
	 }

	for(i=0;i<K;i++) encoder_memory+=shift_register_length[i];


	U=new unsigned int [K]; for(i=0;i<K;i++) U[i]=0;
	V=new unsigned int [N]; for(i=0;i<N;i++) V[i]=0;

	STATE=new unsigned int * [K];
	for(i=0;i<K;i++) STATE[i]=new unsigned int [(M+1)];

	for(i=0;i<K;i++)
	 for(j=0;j<(M+1);j++) STATE[i][j]=0;

	state_number=pow((double)2.0,(double)encoder_memory);

	k_number=pow(2.0,(double)K); n_number=pow(2.0,(double)N);

   // Matriz de transicao de estados
	D=new unsigned int * [state_number];
	for(i=0;i<state_number;i++) D[i]=new unsigned int [k_number];

	for(i=0;i<state_number;i++)
	 for(j=0;j<k_number;j++) D[i][j]=0;

   // Matriz da sequencia de saida
	D1=new unsigned int * [state_number];
	for(i=0;i<state_number;i++) D1[i]=new unsigned int [k_number];

	for(i=0;i<state_number;i++)
	 for(j=0;j<k_number;j++) D1[i][j]=0;

	information=new unsigned int * [k_number];
	for(i=0;i<k_number;i++) information[i]=new unsigned int [K];

   rsc_generate_state_diagram();
	rsc_generate_state_diagram_1();

	//for(i=0;i<K;i++) cout << "\n" << shift_register_length[i];
	//cout << "\n" << encoder_memory;
	//cin.get();

	//for(i=0;i<state_number;i++) { cout << "\n"; for(j=0;j<k_number;j++) cout << D[i][j] << "  "; }
   //cin.get(); cout << "\n\n";
	//for(i=0;i<state_number;i++) { cout << "\n"; for(j=0;j<k_number;j++) cout << D1[i][j] << "  "; }
  	//cin.get();

   zerotail_bits=new unsigned int [M];

   // Initialize Random Interleaving Vector
	RIM=new unsigned int [ZEROTAIL_SIZE];
   FILE * Interleaving;
  	//Interleaving=fopen("inter97.dat","r");
   //Interleaving=fopen("inter256.dat","r");
  	Interleaving=fopen("interlivro.dat","r");
  	for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIM[i]); RIM[i]=RIM[i]-1; }
  	fclose(Interleaving);


   // Initialize Random Interleaving Vector
	RIMa=new unsigned int [ZEROTAIL_SIZE];
  	//Interleaving=fopen("inter97a.dat","r");
   //Interleaving=fopen("inter97.dat","r");
  	//for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIMa[i]); RIMa[i]=RIMa[i]-1; }
  	//fclose(Interleaving);

   // Initialize Random Interleaving Vector
	RIMb=new unsigned int [ZEROTAIL_SIZE];
  	//Interleaving=fopen("inter97b.dat","r");
   //Interleaving=fopen("inter97.dat","r");
  	//for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIMb[i]); RIMb[i]=RIMb[i]-1; }
  	//fclose(Interleaving);

   // Initialize Random Interleaving Vector
	RIMc=new unsigned int [ZEROTAIL_SIZE];
  	//Interleaving=fopen("inter97c.dat","r");
   //Interleaving=fopen("inter97.dat","r");
  	//for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIMc[i]); RIMc[i]=RIMc[i]-1; }
  	//fclose(Interleaving);

   // Initialize Random Interleaving Vector
	RIMd=new unsigned int [ZEROTAIL_SIZE];
  	//Interleaving=fopen("inter97d.dat","r");
   //Interleaving=fopen("inter97.dat","r");
  	//for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIMd[i]); RIMd[i]=RIMd[i]-1; }
  	//fclose(Interleaving);

   // Initialize Random Interleaving Vector
	RIMe=new unsigned int [ZEROTAIL_SIZE];
  	//Interleaving=fopen("inter97e.dat","r");
   //Interleaving=fopen("inter97.dat","r");
  	//for (i=0;i<ZEROTAIL_SIZE;i++) { fscanf(Interleaving,"%d",&RIMe[i]); RIMe[i]=RIMe[i]-1; }
  	//fclose(Interleaving);

}


// Destrutor da Classe do Codificador Convolucional Recursivo Sistematico
rsc_encoder::~rsc_encoder()
{
	unsigned int i,j;

	for(i=0;i<state_number;i++) delete [] D[i]; delete [] D;
	for(i=0;i<state_number;i++) delete [] D1[i]; delete [] D1;

   delete [] shift_register_length;

	for(i=0;i<N;i++)
	 for(j=0;j<K;j++) delete[] G[i][j];

	for(i=0;i<N;i++) delete[] G[i]; delete[] G;

	for(i=0;i<K;i++) delete[] STATE[i]; delete[] STATE;

	delete[] U; delete[] V;

	for(i=0;i<k_number;i++) delete [] information[i]; delete [] information;

}







// Codificador Sistematico de taxa R=1/2
unsigned int * rsc_encoder::systematic_convolutional_encoder(unsigned int * _U)
{
	unsigned int i;
   STATE[0][0]=_U[0];
   //STATE[0][0]=(STATE[0][0]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2]+G[0][0][3]*STATE[0][3])%2;
   //V[0]=_U[0]; V[1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2]+G[1][0][3]*STATE[0][3])%2;
   STATE[0][0]=(STATE[0][0]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
   V[0]=_U[0]; V[1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2])%2;

   for(i=0;i<M;i++) STATE[0][M-i]=STATE[0][M-i-1];
	unsigned int * copysequence=new unsigned int [N]; for(i=0;i<N;i++) copysequence[i]=V[i];
	return copysequence;

}







unsigned int * rsc_encoder::random_interleaving(unsigned int * input_sequence)
{
  unsigned int a,b,i,j,k;
  unsigned int * output_sequence;

  output_sequence=new unsigned int [ZEROTAIL_SIZE];

  for(i=0;i<ZEROTAIL_SIZE;i++) output_sequence[i]=input_sequence[RIM[i]];

  return output_sequence;
}


unsigned int * rsc_encoder::random_deinterleaving(unsigned int * input_sequence)
{
  unsigned int i;
  unsigned int * output_sequence;

  output_sequence=new unsigned int [ZEROTAIL_SIZE];

  for(i=0;i<ZEROTAIL_SIZE;i++) output_sequence[RIM[i]]=input_sequence[i];

  return output_sequence;
}








long double * rsc_encoder::random_interleaving_2(long double * input_sequence)
{
  unsigned int i;
  long double * output_sequence;

  output_sequence=new long double [ZEROTAIL_SIZE];

  for(i=0;i<ZEROTAIL_SIZE;i++) output_sequence[i]=input_sequence[RIM[i]];

  return output_sequence;
}



long double * rsc_encoder::random_deinterleaving_2(long double * input_sequence)
{
  unsigned int i;
  long double * output_sequence;

  output_sequence=new long double [ZEROTAIL_SIZE];

  for(i=0;i<ZEROTAIL_SIZE;i++) output_sequence[RIM[i]]=input_sequence[i];

  return output_sequence;
}






unsigned int * rsc_encoder::get_tailbiting_sequence(unsigned int * _U)
{
  unsigned int i,j,k=0;
  unsigned int * VTAIL;

  VTAIL=new unsigned int [(2*ZEROTAIL_SIZE)];

  rsc_set_state(0);

  for(i=0;i<ZEROTAIL_SIZE;i++)
  {
  	  STATE[0][0]=_U[i];
     STATE[0][0]=(STATE[0][0]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
     VTAIL[k]=_U[i];
     VTAIL[k+1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2])%2;
     for(j=0;j<M;j++) STATE[0][M-j]=STATE[0][M-j-1];
     k=k+2;
  }

  //cout << "\nTail State = " << rsc_get_state(); cin.get();

  return VTAIL;
}




unsigned int * rsc_encoder::get_zerotail_sequence(unsigned int * _U)
{
  unsigned int i,j,k=0;
  unsigned int * VTAIL;

  VTAIL=new unsigned int [(2*ZEROTAIL_SIZE)];

  rsc_set_state(0);

  for(i=0;i<(ZEROTAIL_SIZE-M);i++)
  {
  	  STATE[0][0]=_U[i];
     STATE[0][0]=(STATE[0][0]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
     VTAIL[k]=_U[i];
     VTAIL[k+1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2])%2;
     for(j=0;j<M;j++) STATE[0][M-j]=STATE[0][M-j-1];
     k=k+2;
  }


  // Zerotail Trellis Termination
  //cout << "\nZero = " << rsc_get_state();

  for(i=0;i<M;i++)
  {
  	  zerotail_bits[i]=(G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
     STATE[0][0]=(zerotail_bits[i]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
     VTAIL[k]=zerotail_bits[i];
     VTAIL[k+1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2])%2;
     for(j=0;j<M;j++) STATE[0][M-j]=STATE[0][M-j-1];
     k=k+2;
  }

  //cout << "\nZero = " << rsc_get_state(); cin.get();

  return VTAIL;
}







unsigned int * rsc_encoder::get_zerotail_sequence_livro(unsigned int * _U)
{
  unsigned int i,j,k=0;
  unsigned int * VTAIL;

  VTAIL=new unsigned int [(2*ZEROTAIL_SIZE)];

  rsc_set_state(0);

  for(i=0;i<ZEROTAIL_SIZE;i++)
   {
  	  STATE[0][0]=_U[i];
     STATE[0][0]=(STATE[0][0]+G[0][0][1]*STATE[0][1]+G[0][0][2]*STATE[0][2])%2;
     VTAIL[k]=_U[i];
     VTAIL[k+1]=(G[1][0][0]*STATE[0][0]+G[1][0][1]*STATE[0][1]+G[1][0][2]*STATE[0][2])%2;
     for(j=0;j<M;j++) STATE[0][M-j]=STATE[0][M-j-1];
     k=k+2;
   }

  //cout << "\nZero = " << rsc_get_state(); cin.get();

  return VTAIL;
}




unsigned int * rsc_encoder::generate_transmitted_sequence(unsigned int * X,unsigned int * Y1,unsigned int * Y2)
{
	unsigned int i,j,k,flag;
	unsigned int * sequence;

   sequence=new unsigned int [(2*ZEROTAIL_SIZE)];

   j=0; k=1; flag=0;

	for(i=0;i<ZEROTAIL_SIZE;i++)
    {
      sequence[j]=X[i];
      if (flag==0) { sequence[k]=Y1[i]; flag=1; }  else { sequence[k]=Y2[i]; flag=0; };
      j=j+2; k=k+2;
    }

	return sequence;
}





long double * rsc_encoder::received_sequence_decoder_1(long double * R)
{
	unsigned int i,j,flag;
	long double * sequence;

   sequence=new long double [(2*ZEROTAIL_SIZE)];

   j=0; flag=0;
	for(i=0;i<ZEROTAIL_SIZE;i++)
    {
      sequence[j]=R[j];
      if (flag==0) { sequence[j+1]=R[j+1]; flag=1; } else { sequence[j+1]=0.0; flag=0; };
      j=j+2;
    }

	return sequence;
}




long double * rsc_encoder::add_extrinsic_information(long double * A,long double * B)
{
	unsigned int i,j,N;
	long double * sequence;

   N=(2*ZEROTAIL_SIZE);

   sequence=new long double [N];  for(i=0;i<N;i++) sequence[i]=A[i];

	j=0; for(i=0;i<ZEROTAIL_SIZE;i++) { sequence[j]=sequence[j]+B[i]; j=j+2; }

	return sequence;
}




long double * rsc_encoder::received_sequence_decoder_2(long double * R)
{
	unsigned int i,j,flag;
	long double * sequence;

   sequence=new long double [(2*ZEROTAIL_SIZE)];

   j=0; flag=1;
	for(i=0;i<ZEROTAIL_SIZE;i++)
    {
      sequence[j]=R[j];
      if (flag==1) { sequence[j+1]=0.0; flag=0; } else { sequence[j+1]=R[j+1]; flag=1; };
      j=j+2;
    }

	return sequence;
}




void rsc_encoder::reset_encoder_state(void)
{
	unsigned int i,j;

	for(i=0;i<K;i++)
	 for(j=0;j<(M+1);j++) STATE[i][j]=0;
}




unsigned int rsc_encoder::rsc_get_state(void)
{
	unsigned int i;
	unsigned int *temp,s;

	temp=new unsigned int [encoder_memory];
	for(i=0;i<encoder_memory;i++) temp[i]=0;

	for(i=0;i<encoder_memory;i++)	temp[i]=STATE[0][i+1];

	s=convert_binary_decimal(temp,encoder_memory); delete [] temp;

	return s;
}




void rsc_encoder::rsc_set_state(unsigned int s)
{
		unsigned int i;
		unsigned int * new_state;

		new_state=convert_decimal_binary(s,encoder_memory);

		for(i=0;i<M;i++) STATE[0][i+1]=new_state[i];
}



// -----------------------------------------------------------------------------
// Monta o Diagrama de Estados do Codificador Convolucional
// -----------------------------------------------------------------------------

void rsc_encoder::rsc_generate_state_diagram(void)
{
		unsigned int i,j,k,a,b;
		unsigned int * binary;
		unsigned int *_U,*_V;
		unsigned int actual_state,next_state,weight,*element;

		_U=new unsigned int [K];

		for(i=0;i<k_number;i++)
		 {
         binary=convert_decimal_binary(i,K);
			for(j=0;j<K;j++) information[i][j]=binary[j];
			delete[] binary;
		 }

		for(a=0;a<state_number;a++)
		 {
			 actual_state=a;

			 for(b=0;b<k_number;b++)
			  {
				 for(j=0;j<K;j++) _U[j]=information[b][j];

				 rsc_set_state(a);

				 _V=systematic_convolutional_encoder(_U);

				 weight=0; for(j=0;j<N;j++) if  (_V[j]>0) weight++;

				 D1[a][b]=convert_binary_decimal(_V,N);

				 delete[] _V;

				 element=new unsigned int [weight+1];
				 for(j=0;j<(weight+1);j++) element[j]=0; element[weight]=1;

				 D[a][b]=rsc_get_state();

				 next_state=D[a][b];

				 delete [] element;

			  }
		 }

   delete [] _U;

	reset_encoder_state();
}






// -----------------------------------------------------------------------------
// Monta o Diagrama de Estados do Codificador Convolucional
// -----------------------------------------------------------------------------
void rsc_encoder::rsc_generate_state_diagram_1(void)
{
		unsigned int i,j,k,a,b=0;
		unsigned int *binary;
		unsigned int *_U,*_V;
		unsigned int actual_state,next_state,weight,*element;

		_U=new unsigned int [K];

		for(i=0;i<k_number;i++)
		 {
       	binary=convert_decimal_binary(i,K);
			for(j=0;j<K;j++) information[i][j]=binary[j];
			delete[] binary;
		 }

		for(a=0;a<state_number;a++)
		 {
			 actual_state=a;

			 for(j=0;j<K;j++) _U[j]=information[0][j];

			 rsc_set_state(a);

          _V=systematic_convolutional_encoder(_U);

			 weight=0; for(j=0;j<N;j++) if  (_V[j]>0) weight++;

			 delete[] _V;

			 element=new unsigned int [weight+1];
			 for(j=0;j<(weight+1);j++) element[j]=0; element[weight]=1;

			 D[a][b]=rsc_get_state();

			 next_state=D[a][b];

			 delete [] element;
		 }

   delete [] _U;

	reset_encoder_state();
}





/* CONVERT BINARY/DECIMAL */
unsigned int rsc_encoder::convert_binary_decimal(unsigned int * binary,unsigned int size)
{
	unsigned int i,j,sum=0;

	for (i=0;i<size;i++) sum+=binary[size-1-i]*pow(2.0,(double)i);

	return (sum);
}


/* CONVERT DECIMAL/BINARY */
unsigned int * rsc_encoder::convert_decimal_binary(unsigned int decimal,unsigned int size)
{
	int e,i,h;
	float a;
	unsigned int * r,* r1,* binary_word,conta=0;

e=0;

if (decimal==0)
	h=1;
else
	{  a=(log((double)decimal)/log((double)2))+1;
		h=(unsigned int) floor(a);
	}

r=new unsigned int [h];
r1=new unsigned int [h];

binary_word=new unsigned int [size];

for(i=0;i<size;i++) binary_word[i]=0;

for (i=0;i<h;i++)	r[i]=0;

for (i=0;i<h;i++)	r1[i]=0;

do
{

if (decimal>(unsigned int) floor(ldexp((double)1,(double)e))) e++;
	else  if (decimal==(unsigned int) floor(ldexp((double)1,(double)e)))
			{
				r[e]=1;
				decimal=0;
			}
			else
			{
			  if (e>0)
				{ e--;
				  r[e]=1;
				  decimal=(decimal-(unsigned int) floor(ldexp((double)1,(double)e)));
				  e=0; }
			}

} while (decimal>0);


for (i=(h-1);i>=0;i--) { r1[conta]=r[i]; conta++; }

for (i=0;i<h;i++) binary_word[size-h+i]=r1[i];

delete [] r; delete [] r1;

return (binary_word);
}



